﻿using OpenCvSharp;
using System.Security.Cryptography;


namespace VNDetection
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");



            test16();

            Console.ReadLine();
        }

        static void test16()
        {
            Mat img = Cv2.ImRead("C:\\Users\\Huanye63\\Desktop\\vn\\vn02横向.jpg");
            // 转 HSV
            Mat hsv = new Mat();
            Cv2.CvtColor(img, hsv, ColorConversionCodes.BGR2HSV);
            // 使用调好的阈值
            Scalar lower = new Scalar(0, 0, 76);
            Scalar upper = new Scalar(119, 255, 167);

            Mat mask = new Mat();
            Cv2.InRange(hsv, lower, upper, mask);

            // 提取 VN 区域
            Mat vnRegion = new Mat();
            Cv2.BitwiseAnd(img, img, vnRegion, mask);


            Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));
            Cv2.MorphologyEx(mask, mask, MorphTypes.Open, kernel);  // 去噪点
            Cv2.MorphologyEx(mask, mask, MorphTypes.Close, kernel); // 补小洞

            Cv2.ImShow("VN Extracted", vnRegion);
            Cv2.WaitKey(0);

            Cv2.CvtColor(vnRegion, vnRegion, ColorConversionCodes.BGR2GRAY);
            Cv2.ImShow("VN Extracted", vnRegion);
            Cv2.WaitKey(0);

            //Cv2.CvtColor(vnRegion, vnRegion, ColorConversionCodes.BGR2HSV);
            //Cv2.ImShow("VN Extracted", vnRegion);
            //Cv2.WaitKey(0);
            Cv2.ImWrite(@"C:\Users\Huanye63\Desktop\vn\vnRegion02.jpg", vnRegion);
        }
        static void test15()
        {
            // 读取图像
            Mat img = Cv2.ImRead(@"C:\Users\Huanye63\Desktop\vn\vn02裁剪.jpg");

            // 转灰度
            Mat gray = new Mat();
            Cv2.CvtColor(img, gray, ColorConversionCodes.BGR2GRAY);

            // 直方图均衡化，提升对比度
            Mat equalized = new Mat();
            Cv2.EqualizeHist(gray, equalized);

            // 自适应阈值（比固定阈值更适合有亮度差异的字符）
            Mat binary = new Mat();
            Cv2.AdaptiveThreshold(equalized, binary, 255,
                AdaptiveThresholdTypes.GaussianC, ThresholdTypes.Binary, 25, 10);

            // 显示
            Cv2.ImShow("vn_fixed.png", binary);
            Cv2.WaitKey(0);

        }
        static void test14()
        {
            // 读取图像
            Mat img = Cv2.ImRead(@"C:\Users\Huanye63\Desktop\vn\vn02裁剪.jpg");


            // 转HSV
            Mat hsv = new Mat();
            Cv2.CvtColor(img, hsv, ColorConversionCodes.BGR2HSV);

            // 定义铜色的范围 (你需要微调)
            Scalar lower = new Scalar(10, 50, 50);   // HMin, SMin, VMin
            Scalar upper = new Scalar(20, 255, 200); // HMax, SMax, VMax

            // 生成掩膜
            Mat mask = new Mat();
            Cv2.InRange(hsv, lower, upper, mask);

            // 对掩膜做二值化
            Cv2.ImWrite("vn_mask.jpg", mask);

            // 可选：用掩膜在原图上提取VN区域
            Mat vnOnly = new Mat();
            Cv2.BitwiseAnd(img, img, vnOnly, mask);
            Cv2.ImWrite("vn_only.jpg", vnOnly);
            //Cv2.ImWrite(@"C:\Users\Huanye63\Desktop\vn\vn_only.jpg", img);
            Cv2.ImShow("VN Only", vnOnly);
            Cv2.WaitKey(0);
        }

        static void test13()
        {
            string tessdataPath = @"D:\Program Files\Tesseract-OCR\tessdata";
            string imagePath = @"C:\Users\Huanye63\Desktop\vn\vn模板03.jpg";

            try
            {
                using (var engine = new Tesseract.TesseractEngine(tessdataPath, "eng", Tesseract.EngineMode.Default))
                {
                    using (var img = Tesseract.Pix.LoadFromFile(imagePath))
                    {
                        using (var page = engine.Process(img))
                        {
                            string text = page.GetText();
                            Console.WriteLine("识别结果：");
                            Console.WriteLine(text);
                            Console.WriteLine($"置信度：{page.GetMeanConfidence()}");
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("出错：" + e.Message);
            }
        }

        static void test12()
        {
            Mat img = Cv2.ImRead(@"C:\Users\Huanye63\Desktop\vn\vn02裁剪.jpg");
            Mat hsv = new Mat();
            Cv2.CvtColor(img, hsv, ColorConversionCodes.BGR2HSV);

            // 创建窗口
            Cv2.NamedWindow("Trackbars", WindowFlags.AutoSize);

            // 创建滑块（初始值可以调大点）
            int hMin = 0, sMin = 0, vMin = 0;
            int hMax = 179, sMax = 255, vMax = 255;

            Cv2.CreateTrackbar("HMin", "Trackbars", ref hMin, 179);
            Cv2.CreateTrackbar("HMax", "Trackbars", ref hMax, 179);
            Cv2.CreateTrackbar("SMin", "Trackbars", ref sMin, 255);
            Cv2.CreateTrackbar("SMax", "Trackbars", ref sMax, 255);
            Cv2.CreateTrackbar("VMin", "Trackbars", ref vMin, 255);
            Cv2.CreateTrackbar("VMax", "Trackbars", ref vMax, 255);

            while (true)
            {
                // 读取滑块的值
                hMin = Cv2.GetTrackbarPos("HMin", "Trackbars");
                hMax = Cv2.GetTrackbarPos("HMax", "Trackbars");
                sMin = Cv2.GetTrackbarPos("SMin", "Trackbars");
                sMax = Cv2.GetTrackbarPos("SMax", "Trackbars");
                vMin = Cv2.GetTrackbarPos("VMin", "Trackbars");
                vMax = Cv2.GetTrackbarPos("VMax", "Trackbars");

                // 根据阈值生成 mask
                Scalar lower = new Scalar(hMin, sMin, vMin);
                Scalar upper = new Scalar(hMax, sMax, vMax);
                Mat mask = new Mat();
                Cv2.InRange(hsv, lower, upper, mask);

                // 应用掩膜
                Mat result = new Mat();
                Cv2.BitwiseAnd(img, img, result, mask);

                Cv2.ImShow("Mask", mask);
                Cv2.ImShow("Result", result);

                if (Cv2.WaitKey(10) == 27) // 按 ESC 退出
                {
                    break;
                }

                Task.Delay(100).Wait();
            }
        }


            static void test11()
            {
                Mat img = Cv2.ImRead(@"C:\Users\Huanye63\Desktop\vn\vn02裁剪.jpg");

                // 转 HSV，便于分离铜色
                Mat hsv = new Mat();
                Cv2.CvtColor(img, hsv, ColorConversionCodes.BGR2HSV);

                // 铜色大致范围 (你可以根据实际调节)
                Scalar lower = new Scalar(0, 60, 50);   // H, S, V 下限
                Scalar upper = new Scalar(25, 255, 200); // H, S, V 上限

                // 提取铜色区域
                Mat mask = new Mat();
                Cv2.InRange(hsv, lower, upper, mask);

                // 可选：做形态学操作，去掉小噪点
                Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));
                Cv2.MorphologyEx(mask, mask, MorphTypes.Open, kernel);
                Cv2.MorphologyEx(mask, mask, MorphTypes.Close, kernel);

                // 结果叠加：铜色区域变白，其余为黑
                Mat result = new Mat();
                Cv2.BitwiseAnd(img, img, result, mask);

                // 保存或显示结果
                Cv2.ImShow("mask", mask);
                Cv2.ImShow("result", result);
                Cv2.WaitKey(0);
            }

            /// <summary>
            /// 暴力匹配
            /// </summary>
            static void test10()
            {
                string sourcePath = @"C:\Users\Huanye63\Desktop\vn\vn02横向.jpg";
                //string sourcePath = @"C:\Users\Huanye63\Desktop\vn\vn02裁剪.jpg";
                string templateVNPath = @"C:\Users\Huanye63\Desktop\vn\vn模板04.jpg";  // 直接用整体 VN 模板

                // 读取图片
                Mat imgtemp = Cv2.ImRead(sourcePath, ImreadModes.Grayscale);
                Mat template = Cv2.ImRead(templateVNPath, ImreadModes.Grayscale);

                Mat img = new Mat();
                Cv2.CvtColor(imgtemp, img, ColorConversionCodes.BGR2GRAY);
                Cv2.EqualizeHist(img, img);   // 直方图均衡
                Cv2.Threshold(img, img, 0, 255, ThresholdTypes.Otsu);


                // 结果矩阵：宽=原图宽-模板宽+1，高=原图高-模板高+1
                Mat result = new Mat(img.Rows - template.Rows + 1, img.Cols - template.Cols + 1, MatType.CV_32FC1);

                // 暴力匹配：平方差、相关性、相关系数都可以试试
                Cv2.MatchTemplate(img, template, result, TemplateMatchModes.CCoeffNormed);

                // 找最大匹配值及位置
                Cv2.MinMaxLoc(result, out double minVal, out double maxVal, out Point minLoc, out Point maxLoc);

                // 在原图上标出匹配位置
                Point matchLoc = maxLoc;
                Cv2.Rectangle(img, matchLoc, new Point(matchLoc.X + template.Cols, matchLoc.Y + template.Rows), Scalar.Red, 2);

                // 显示结果
                Cv2.ImShow("Matched Image", img);
                Cv2.ImWrite(@"C:\Users\Huanye63\Desktop\vn\vn02横向灰度图.jpg", img);
                Cv2.WaitKey(0);


                //Mat src = Cv2.ImRead("C:\\Users\\Huanye63\\Desktop\\vn\\vn02横向.jpg");
                //Mat templateVN = Cv2.ImRead("C:\\Users\\Huanye63\\Desktop\\vn\\vn02横向.jpg");

                //// 2. 转换为 HSV
                //Mat src02 = new Mat();
                //Cv2.CvtColor(src, src02, ColorConversionCodes.BGR2GRAY);
                //Mat templateVN2 = new Mat();
                //Cv2.CvtColor(templateVN, templateVN2, ColorConversionCodes.BGR2GRAY);

                //Cv2.

            }


            static void test09()
            {
                // 读取原图
                Mat src = Cv2.ImRead("C:\\Users\\Huanye63\\Desktop\\vn\\vn02横向.jpg");
                if (src.Empty())
                {
                    Console.WriteLine("无法加载图片");
                    return;
                }

                // 转 HSV
                Mat hsvImg = new Mat();
                Cv2.CvtColor(src, hsvImg, ColorConversionCodes.BGR2HSV);

                // VN 的 HSV 范围
                Scalar lower = new Scalar(98, 52, 46);   // H-10, S-40, V-40
                Scalar upper = new Scalar(118, 132, 126); // H+10, S+40, V+40

                // 生成掩膜
                Mat mask = new Mat();
                Cv2.InRange(hsvImg, lower, upper, mask);

                // 提取结果（只显示 VN 部分）
                Mat result = new Mat();
                Cv2.BitwiseAnd(src, src, result, mask);

                // 保存结果
                Cv2.ImWrite("VN_mask.jpg", mask);
                Cv2.ImWrite("VN_result.jpg", result);

                Console.WriteLine("VN 区域提取完成，结果已保存。");
            }
            static void test08()
            {
                string imagePath = "C:\\Users\\Huanye63\\Desktop\\vn\\vn02横向.jpg";
                Mat img = Cv2.ImRead(imagePath);
                if (img.Empty())
                {
                    Console.WriteLine("无法加载图像: " + imagePath);
                    return;
                }

                // 转换到 HSV
                Mat hsv = new Mat();
                Cv2.CvtColor(img, hsv, ColorConversionCodes.BGR2HSV);

                // 窗口
                Cv2.NamedWindow("Mask", WindowFlags.FreeRatio);

                // 创建 Trackbars
                int hMin = 0, sMin = 0, vMin = 0;
                int hMax = 179, sMax = 255, vMax = 255;

                Cv2.CreateTrackbar("H Min", "Mask", ref hMin, 179);
                Cv2.CreateTrackbar("H Max", "Mask", ref hMax, 179);
                Cv2.CreateTrackbar("S Min", "Mask", ref sMin, 255);
                Cv2.CreateTrackbar("S Max", "Mask", ref sMax, 255);
                Cv2.CreateTrackbar("V Min", "Mask", ref vMin, 255);
                Cv2.CreateTrackbar("V Max", "Mask", ref vMax, 255);

                while (true)
                {
                    Scalar lower = new Scalar(hMin, sMin, vMin);
                    Scalar upper = new Scalar(hMax, sMax, vMax);

                    Mat mask = new Mat();
                    Cv2.InRange(hsv, lower, upper, mask);

                    Mat result = new Mat();
                    Cv2.BitwiseAnd(img, img, result, mask);

                    // 显示结果
                    Cv2.ImShow("Mask", result);

                    int key = Cv2.WaitKey(30);
                    if (key == 27) // 按 ESC 退出
                    {
                        Cv2.ImWrite(@"C:\Users\Huanye63\Desktop\vn\Mask_final.jpg", mask);
                        break;
                    }
                }

                Cv2.DestroyAllWindows();
            }
            static void test07()
            {
                string inputPath = "C:\\Users\\Huanye63\\Desktop\\vn\\vn02横向.jpg";
                string templateVNPath = @"C:\Users\Huanye63\Desktop\vn\vn模板02.jpg";  // 直接用整体 VN 模板

                // 1. 读取图像
                string imgPath = inputPath; // 你的输入图
                Mat img = Cv2.ImRead(imgPath);

                // 2. 转换为 HSV
                Mat hsv = new Mat();
                Cv2.CvtColor(img, hsv, ColorConversionCodes.BGR2HSV);

                // 3. 定义阈值范围（你调试好的值）
                Scalar lower = new Scalar(0, 0, 76);   // HMin, SMin, VMin
                Scalar upper = new Scalar(119, 255, 167); // HMax, SMax, VMax

                // 4. 颜色过滤
                Mat mask = new Mat();
                Cv2.InRange(hsv, lower, upper, mask);

                // 5. 找轮廓
                Cv2.FindContours(mask, out Point[][] contours, out HierarchyIndex[] hierarchy,
                    RetrievalModes.External, ContourApproximationModes.ApproxSimple);

                Cv2.ImShow("123", mask);
                Cv2.WaitKey();

                bool found = false;
                foreach (var contour in contours)
                {
                    double area = Cv2.ContourArea(contour);
                    if (area > 50) // 过滤掉太小的点
                    {
                        found = true;
                        Rect rect = Cv2.BoundingRect(contour);
                        Cv2.Rectangle(img, rect, Scalar.Green, 2); // 在原图画框
                    }
                }

                // 6. 输出结果
                if (found)
                {
                    Console.WriteLine("PASS: 检测到 VN 区域");
                    Cv2.ImWrite("result_pass.jpg", img);
                }
                else
                {
                    Console.WriteLine("FAIL: 未检测到 VN");
                    Cv2.ImWrite("result_fail.jpg", img);
                }
            }
            static void test06()
            {
                string inputPath = "C:\\Users\\Huanye63\\Desktop\\vn\\vn02横向.jpg";
                string templateVNPath = @"C:\Users\Huanye63\Desktop\vn\vn模板02.jpg";  // 直接用整体 VN 模板

                Mat img = Cv2.ImRead(inputPath);
                if (img.Empty())
                {
                    Console.WriteLine("无法加载 input.jpg");
                    return;
                }

                // 1. 转 HSV
                Mat hsv = new Mat();
                Cv2.CvtColor(img, hsv, ColorConversionCodes.BGR2HSV);

                // 2. 使用你调好的阈值
                Scalar lower = new Scalar(0, 0, 76);
                Scalar upper = new Scalar(119, 255, 167);
                Mat mask = new Mat();
                Cv2.InRange(hsv, lower, upper, mask);
                Cv2.ImShow("Mask", mask);
                Cv2.WaitKey(0);
                Cv2.ImWrite(@"C:\Users\Huanye63\Desktop\vn\Mask.jpg", mask);

                // 3. 去噪
                Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));
                Cv2.MorphologyEx(mask, mask, MorphTypes.Open, kernel);
                Cv2.MorphologyEx(mask, mask, MorphTypes.Close, kernel);

                // 4. 找轮廓，取最大区域作为 ROI
                Cv2.FindContours(mask, out Point[][] contours, out _, RetrievalModes.External, ContourApproximationModes.ApproxSimple);

                if (contours.Length == 0)
                {
                    Console.WriteLine("未检测到疑似 VN 区域");
                    return;
                }

                // 按面积排序，取最大
                int maxIndex = 0;
                double maxArea = 0;
                for (int i = 0; i < contours.Length; i++)
                {
                    double area = Cv2.ContourArea(contours[i]);
                    if (area > maxArea)
                    {
                        maxArea = area;
                        maxIndex = i;
                    }
                }

                Rect rect = Cv2.BoundingRect(contours[maxIndex]);
                Mat roi = new Mat(img, rect);

                // 5. 读取 VN 模板
                Mat templateVN = Cv2.ImRead(templateVNPath, ImreadModes.Grayscale);
                if (templateVN.Empty())
                {
                    Console.WriteLine("模板未加载，请准备 VN_template.jpg");
                    return;
                }

                // 灰度处理 ROI
                Mat roiGray = new Mat();
                Cv2.CvtColor(roi, roiGray, ColorConversionCodes.BGR2GRAY);

                // 6. 模板匹配
                Mat result = new Mat();
                Cv2.MatchTemplate(roiGray, templateVN, result, TemplateMatchModes.CCoeffNormed);
                Cv2.MinMaxLoc(result, out _, out double maxVal, out _, out Point maxLoc);

                Console.WriteLine($"VN 匹配度: {maxVal:F2}");

                if (maxVal > 0.7)  // 阈值可调
                {
                    Console.WriteLine("检测到 VN ✅");
                    Cv2.Rectangle(img, rect, Scalar.Red, 2);
                }
                else
                {
                    Console.WriteLine("未检测到 VN ❌");
                }

                // 7. 显示结果
                Cv2.ImShow("Mask", mask);
                Cv2.WaitKey(0);

                Cv2.ImShow("ROI", roi);
                Cv2.WaitKey(0);
                Cv2.ImShow("Result", img);
                Cv2.WaitKey(0);
            }
            static void test05()
            {
                Mat img = Cv2.ImRead("C:\\Users\\Huanye63\\Desktop\\vn\\vn02横向.jpg");
                // 转 HSV
                Mat hsv = new Mat();
                Cv2.CvtColor(img, hsv, ColorConversionCodes.BGR2HSV);
                // 使用调好的阈值
                Scalar lower = new Scalar(0, 0, 76);
                Scalar upper = new Scalar(119, 255, 167);

                Mat mask = new Mat();
                Cv2.InRange(hsv, lower, upper, mask);

                // 提取 VN 区域
                Mat vnRegion = new Mat();
                Cv2.BitwiseAnd(img, img, vnRegion, mask);


                Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));
                Cv2.MorphologyEx(mask, mask, MorphTypes.Open, kernel);  // 去噪点
                Cv2.MorphologyEx(mask, mask, MorphTypes.Close, kernel); // 补小洞

                Cv2.ImShow("VN Extracted", vnRegion);
                Cv2.WaitKey(0);
                Cv2.ImWrite(@"C:\Users\Huanye63\Desktop\vn\vnRegion.jpg", vnRegion);
            }
            static void test04()
            {
                string imagePath = "C:\\Users\\Huanye63\\Desktop\\vn\\vn02横向.jpg";
                Mat img = Cv2.ImRead(imagePath);
                if (img.Empty())
                {
                    Console.WriteLine("无法加载图像: " + imagePath);
                    return;
                }

                // 转换到 HSV
                Mat hsv = new Mat();
                Cv2.CvtColor(img, hsv, ColorConversionCodes.BGR2HSV);

                // 窗口
                Cv2.NamedWindow("Mask", WindowFlags.AutoSize);

                // 创建 Trackbars
                int hMin = 0, sMin = 0, vMin = 0;
                int hMax = 179, sMax = 255, vMax = 255;

                Cv2.CreateTrackbar("H Min", "Mask", ref hMin, 179);
                Cv2.CreateTrackbar("H Max", "Mask", ref hMax, 179);
                Cv2.CreateTrackbar("S Min", "Mask", ref sMin, 255);
                Cv2.CreateTrackbar("S Max", "Mask", ref sMax, 255);
                Cv2.CreateTrackbar("V Min", "Mask", ref vMin, 255);
                Cv2.CreateTrackbar("V Max", "Mask", ref vMax, 255);

                while (true)
                {
                    Scalar lower = new Scalar(hMin, sMin, vMin);
                    Scalar upper = new Scalar(hMax, sMax, vMax);

                    Mat mask = new Mat();
                    Cv2.InRange(hsv, lower, upper, mask);

                    Mat result = new Mat();
                    Cv2.BitwiseAnd(img, img, result, mask);

                    // 显示结果
                    Cv2.ImShow("Mask", result);

                    int key = Cv2.WaitKey(30);
                    if (key == 27) // 按 ESC 退出
                        break;
                }

                Cv2.DestroyAllWindows();
            }

            static void DetectVN03()
            {
                // 1. 读取目标图像
                Mat img = Cv2.ImRead("C:\\Users\\Huanye63\\Desktop\\vn\\vn02横向.jpg", ImreadModes.Color);
                if (img.Empty())
                {
                    Console.WriteLine("无法加载 input.jpg");
                    return;
                }

                // 2. 转换为灰度
                Mat gray = new Mat();
                Cv2.CvtColor(img, gray, ColorConversionCodes.BGR2GRAY);
                //Cv2.ImShow("Result", gray);
                //Cv2.WaitKey(0);
                //// 释放窗口
                //Cv2.DestroyAllWindows();


                // 3. 简单二值化（如果色泽差异大，可以先用 InRange 做颜色分割）
                Mat binary = new Mat();
                Cv2.Threshold(gray, binary, 0, 255, ThresholdTypes.Otsu);

                // 4. 读取模板
                //Mat templateVN = Cv2.ImRead("C:\\Users\\Huanye63\\Desktop\\vn\\vn模板01.png", ImreadModes.Grayscale);
                Mat templateVN = Cv2.ImRead(@"C:\Users\Huanye63\Desktop\vn\vn模板02.jpg", ImreadModes.Grayscale);

                if (templateVN.Empty())
                {
                    Console.WriteLine("模板图片未找到！");
                    return;
                }

                // 5. 模板匹配 - V
                Mat resultV = new Mat();
                Cv2.MatchTemplate(binary, templateVN, resultV, TemplateMatchModes.CCoeff);
                Cv2.MinMaxLoc(resultV, out _, out double maxValVN, out _, out Point maxLocVN);

                Console.WriteLine($"VN 匹配度: {maxValVN:F2}");

                // 7. 判断是否检测到 VN
                if (maxValVN > 0.9) // 阈值可调
                {
                    Console.WriteLine("检测到 VN！");
                    // 在图像上画矩形标记（示例）
                    Cv2.Rectangle(img, new Rect(maxLocVN, templateVN.Size()), Scalar.Red, 2);
                    //Cv2.Rectangle(img, new Rect(maxLocN, templateN.Size()), Scalar.Green, 2);
                }
                else
                {
                    Console.WriteLine("未检测到 VN！");
                }

                Cv2.Rectangle(img, new Rect(maxLocVN, templateVN.Size()), Scalar.Red, 2);

                //// 8. 显示结果
                Cv2.ImShow("Result", img);
                //Cv2.WaitKey(0);
            }


            /// <summary>
            /// 检测VN0(颜色检测)
            /// </summary>
            /// <param name="img"></param>
            static void DetectVN02(Mat img)
            {
                // 转换颜色空间
                Mat hsv = new Mat();
                Cv2.CvtColor(img, hsv, ColorConversionCodes.BGR2HSV);

                // 假设VN是某种特定色泽，比如偏红
                Scalar lower = new Scalar(0, 100, 100);
                Scalar upper = new Scalar(10, 255, 255);
                Mat mask = new Mat();
                Cv2.InRange(hsv, lower, upper, mask);

                // 做形态学操作，去噪
                Cv2.MorphologyEx(mask, mask, MorphTypes.Open, Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3)));
                // 显示结果
                Cv2.ImShow("Contours", mask);

                //Mat roi = img[rect]; // 裁剪VN区域
                //Mat templateV = Cv2.ImRead("V_template.jpg", ImreadModes.Grayscale);
                //Mat templateN = Cv2.ImRead("N_template.jpg", ImreadModes.Grayscale);

                //Mat resultV = new Mat();
                //Cv2.MatchTemplate(roi, templateV, resultV, TemplateMatchModes.CCoeffNormed);
                //Cv2.MinMaxLoc(resultV, out _, out double maxValV);

                //Mat resultN = new Mat();
                //Cv2.MatchTemplate(roi, templateN, resultN, TemplateMatchModes.CCoeffNormed);
                //Cv2.MinMaxLoc(resultN, out _, out double maxValN);

                //if (maxValV > 0.7 && maxValN > 0.7)
                //{
                //    Console.WriteLine("检测到 VN");
                //}

            }

            /// <summary>
            /// 检测VN01(轮廓检测)
            /// </summary>
            /// <param name="img"></param>
            static void DetectVN01(Mat img)
            {
                // 转换为灰度图像
                Mat gray = new Mat();
                Cv2.CvtColor(img, gray, ColorConversionCodes.BGR2GRAY);
                // 使用高斯模糊去噪
                Mat blurred = new Mat();
                Cv2.GaussianBlur(gray, blurred, new Size(5, 5), 0);
                // 边缘检测
                Mat edges = new Mat();
                Cv2.Canny(blurred, edges, 50, 150);
                // 查找轮廓
                Point[][] contours;
                HierarchyIndex[] hierarchy;
                Cv2.FindContours(edges, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
                // 绘制轮廓
                Mat contourImg = img.Clone();
                Cv2.DrawContours(contourImg, contours, -1, new Scalar(0, 255, 0), 2);
                // 显示结果
                Cv2.ImShow("Contours", contourImg);
                Cv2.WaitKey(0);
            }



        }
    }
